<template>
  <div>
    <div id="sphere" ref="sphere"></div>
    <div class="screen-block">
      <canvas id="my-canvas"></canvas>
    </div>
  </div>
</template>

<script>
const THREE = require("three");
const TWEEN = require("@tweenjs/tween.js");
import "@/utils/CSS3DRenderer";
import "@/utils/TrackballControls";
import {
  getMonthStartDate,
  getMonthEndDate,
  getWeek
} from "@/utils/getCurrMonth";

export default {
  name: "sphere",
  data() {
    return {
      colors: {
        visit: "rgba(111,86,181,.3)",
        sign: "rgba(0,127,127,.5)",
        pick: "rgba(29,91,175,.5)"
      },
      table: [],
      sphere: [],
      time: [getMonthStartDate(), getMonthEndDate()],
      objects: [],
      controls: {},
      camera: {},
      scene: {},
      renderer: {},
      timer: null
    };
  },
  mounted() {
    this.handleScreenSphere();
    this.timer = setInterval(() => {
      this.handleScreenSphere();
    }, 1000 * 60 * 30);
    var c = document.getElementById("my-canvas");
    var ctx = c.getContext("2d");
    const option = {
      legend: {
        x: "0",
        y: "0",
        color: [
          "rgba(111,86,181,.3)",
          "rgba(0,127,127,.5)",
          "rgba(29,91,175,.5)"
        ],
        data: ["上门", "签单", "提车"],
        itemGap: "25",
        itemWidth: "25",
        itemHeight: "13",
        textStyle: {
          color: "#ccc",
          fontSize: 12
        }
      }
    };
    option.legend.data.forEach((item, i) => {
      this.drawRoundedRect(
        ctx,
        +option.legend.x,
        +option.legend.y + +option.legend.itemGap * i,
        +option.legend.itemWidth,
        +option.legend.itemHeight,
        2,
        true,
        false,
        option.legend.color[i],
        option.legend.textStyle.color,
        item
      );
    });
  },
  methods: {
    drawRoundedRect(
      ctx,
      x,
      y,
      width,
      height,
      r,
      fill,
      stroke,
      color,
      fontColor,
      content
    ) {
      ctx.save();
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.fillStyle = color;
      // 使用arcTo()方法画四个角
      ctx.arcTo(x + width, y, x + width, y + r, r);
      ctx.arcTo(x + width, y + height, x + width - r, y + height, r);
      ctx.arcTo(x, y + height, x, y + height - r, r);
      ctx.arcTo(x, y, x + r, y, r);

      if (fill) {
        ctx.fill();
      }
      if (stroke) {
        ctx.stroke();
      }
      ctx.restore();
      this.drawText(ctx, x, y, width, height, fill, stroke, fontColor, content);
    },
    drawText(ctx, x, y, width, height, fill, stroke, fontColor, content) {
      ctx.save();
      ctx.beginPath(); // draw top and top right corner
      ctx.font = "18px";
      ctx.fillStyle = fontColor;
      ctx.textBaseline = "bottom";
      ctx.fillText(content, x + width + 5, y + height);
      if (fill) {
        ctx.fill();
      }
      if (stroke) {
        ctx.stroke();
      }
      ctx.restore();
    },
    resetData() {
      this.init();
      this.animate();
      this.transform(this.sphere, 1000);
    },
    handleScreenSphere() {
      this.table = [];
      this.$axios
        .post("/api/screen/screenSphere", {
          from: getWeek().start,
          to: getWeek().end
        })
        .then(data => {
          this.table = data;
        })
        .then(() => {
          this.resetData();
        });
    },
    changeColor() {
      const sphere = this.$refs.sphere;
      const ele = [].slice.call(sphere.getElementsByClassName("details"));
      ele.forEach(item => {
        if (item.innerHTML.includes("上门")) {
          item.parentNode.style.background = this.colors.visit;
        }
        if (item.innerHTML.includes("签订")) {
          item.parentNode.style.background = this.colors.sign;
        }
        if (item.innerHTML.includes("提车")) {
          item.parentNode.style.background = this.colors.pick;
        }
      });
    },
    init() {
      this.sphere = [];
      this.objects = [];
      this.controls = {};
      this.camera = {};
      this.scene = {};
      this.renderer = {};
      document.getElementById("sphere").innerHTML = "";
      this.camera = new THREE.PerspectiveCamera(
        40,
        window.innerWidth / window.innerHeight,
        1,
        10000
      );
      this.camera.position.z = 3900; // 设置缩放尺寸
      this.scene = new THREE.Scene();
      // table

      for (var i = 0; i < this.table.length; i += 5) {
        let element = document.createElement("div");
        element.className = "element";
        element.style.backgroundColor =
          "rgba(0,127,127," + (Math.random() * 0.5 + 0.25) + ")";

        // 编号
        let number = document.createElement("div");
        number.className = "number";
        number.textContent = i / 5 + 1;
        element.appendChild(number);

        // 标题
        let symbol = document.createElement("div");
        symbol.className = "symbol";
        symbol.textContent = this.table[i];
        element.appendChild(symbol);

        // 详细内容
        let details = document.createElement("div");
        details.className = "details";
        details.innerHTML = this.table[i + 1] + "<br>" + this.table[i + 2];
        element.appendChild(details);

        let object = new THREE.CSS3DObject(element);
        object.position.x = Math.random() * 4000 - 2000;
        object.position.y = Math.random() * 4000 - 2000;
        object.position.z = Math.random() * 4000 - 2000;
        this.scene.add(object);
        this.objects.push(object);
      }
      // sphere

      let vector = new THREE.Vector3();
      let spherical = new THREE.Spherical();

      for (var i = 0, l = this.objects.length; i < l; i++) {
        let phi = Math.acos(-1 + (2 * i) / l);
        let theta = Math.sqrt(l * Math.PI) * phi;
        let object = new THREE.Object3D();
        spherical.set(800, phi, theta);
        object.position.setFromSpherical(spherical);
        vector.copy(object.position).multiplyScalar(2);
        object.lookAt(vector);
        this.sphere.push(object);
      }
      //

      this.renderer = new THREE.CSS3DRenderer();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.domElement.style.position = "absolute";
      document.getElementById("sphere").appendChild(this.renderer.domElement);
      //

      this.controls = new THREE.TrackballControls(
        this.camera,
        this.renderer.domElement
      );
      this.controls.rotateSpeed = 0.5;
      this.controls.minDistance = 500;
      this.controls.maxDistance = 6000;
      this.controls.addEventListener("change", this.render);
      this.controls.target.y = -350; // 设置y轴位移
      this.controls.target.x = 260; // 设置x轴位移
      window.addEventListener("resize", this.onWindowResize, false);
    },
    transform(targets, duration) {
      TWEEN.removeAll();
      for (var i = 0; i < this.objects.length; i++) {
        let object = this.objects[i];
        let target = targets[i];
        new TWEEN.Tween(object.position)
          .to(
            {
              x: target.position.x,
              y: target.position.y,
              z: target.position.z
            },
            Math.random() * duration + duration
          )
          .easing(TWEEN.Easing.Exponential.InOut)
          .start();
        new TWEEN.Tween(object.rotation)
          .to(
            {
              x: target.rotation.x,
              y: target.rotation.y,
              z: target.rotation.z
            },
            Math.random() * duration + duration
          )
          .easing(TWEEN.Easing.Exponential.InOut)
          .start();
      }
      new TWEEN.Tween(this)
        .to({}, duration * 2)
        .onUpdate(this.render)
        .start();
      this.changeColor();
    },
    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.render();
    },
    animate() {
      this.scene.rotation.y += 0.002;
      requestAnimationFrame(this.animate);
      TWEEN.update();
      this.controls.update();
      this.render();
    },
    render() {
      this.renderer.render(this.scene, this.camera);
    },
    beforDestoy() {
      clearInterval(this.timer);
    }
  }
};
</script>
<style >
</style>